package com.oglvip.business.web.controller;

import com.oglvip.business.conf.spring.WebSecurityConfig;
import com.oglvip.business.consts.common.Consts;
import com.oglvip.business.consts.common.ResponseCode;
import com.oglvip.business.dto.ForgetPwdFormDto;
import com.oglvip.business.dto.RegisterFormDto;
import com.oglvip.business.dto.ResponseData;
import com.oglvip.business.remote.service.api.StoreAccountService;
import com.oglvip.business.remote.service.entity.StoreAccount;
import com.oglvip.business.util.CookieHolder;
import com.oglvip.business.util.CookieUtils;
import com.oglvip.business.util.EncryptUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.Md5Crypt;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.UUID;

/**
 * @auther hanchao
 * @date 2016/11/27 12:42
 */
@RestController
@RequestMapping("/account")
public class AccountController {
    @Autowired
    private StoreAccountService accountService;
    @Autowired
    private WebSecurityConfig webSecurityConfig;


    @RequestMapping("modifypwd")
    public ResponseData modifypwd(String oldPass,String newPass){
        ResponseData result = ResponseData.builder().build();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        try {
            StoreAccount account = (StoreAccount) authentication.getPrincipal();
            result = accountService.modifypwd(account.getTicket(),EncryptUtil.md5Encrypt(oldPass),EncryptUtil.md5Encrypt(newPass));
        } catch(Exception e){
            result.setResponseCode(ResponseCode.UNAUTHORIZED);
        }
        return result;
    }

    @RequestMapping("/tologin")
    public ResponseData tologin() {
        ResponseData result = ResponseData.builder().build();
        result.setResponseCode(ResponseCode.UNAUTHORIZED);
        return result;
    }

    @RequestMapping("/success")
    public ResponseData success(HttpServletRequest request, HttpServletResponse response) {
        ResponseData result = ResponseData.builder().build();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        result.setResponseCode(ResponseCode.SUCCESS);

        if (request.getParameter("rememberMe") != null && request.getParameter("rememberMe").equals("true")) { //如果需要设置cookie
            String uuid = UUID.randomUUID().toString();
            String cookieValue = Base64.encodeBase64String(Md5Crypt.md5Crypt(uuid.getBytes()).getBytes());
            CookieUtils.setCookie(response, Consts.REMEMBER_COOKIE, cookieValue, "", Consts.REMEMBER_AGE, false);
            CookieHolder.put(cookieValue, (StoreAccount) authentication.getPrincipal());
        }

        result.setData(getAccount(authentication));

        return result;
    }

    @RequestMapping("/fail")
    public ResponseData fail(HttpServletRequest request) {
        ResponseData result = ResponseData.builder().build();
        result.setResponseCode(ResponseCode.LOGIN_FAILED);
        result.setMessage(((AuthenticationException) request.getAttribute("SPRING_SECURITY_LAST_EXCEPTION")).getMessage());
        return result;
    }

    @RequestMapping("/get")
    public ResponseData getAccount(HttpServletRequest request, HttpServletResponse response) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        ResponseData result = ResponseData.builder().build();
        if (authentication.getPrincipal() instanceof StoreAccount) {
            result.setResponseCode(ResponseCode.SUCCESS);
            result.setData(getAccount(authentication));
        } else {
            result.setResponseCode(ResponseCode.UNAUTHORIZED);
        }
        return result;
    }

    @RequestMapping("/password/forget")
    public ResponseData forgetPass(ForgetPwdFormDto dto) {
        dto.setNewPassword(EncryptUtil.md5Encrypt(dto.getNewPassword()));
        return accountService.forgetPwd(dto);
    }

    @RequestMapping("/register")
    public ResponseData register(@Valid RegisterFormDto dto, HttpServletRequest request) {
        dto.setPassword(EncryptUtil.md5Encrypt(dto.getPassword()));
        ResponseData data = accountService.register(dto);
        if(data.getCode() == 0){
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(dto.getPhone(), dto.getPassword());
            try {
                token.setDetails(new WebAuthenticationDetails(request));
                Authentication authenticatedUser = webSecurityConfig.getAuthenticationManager().authenticate(token);

                SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
                request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
            } catch (AuthenticationException e) {
                System.out.println("Authentication failed: " + e.getMessage());
            }
        }
        return data;
    }


    /**
     * 返回给用户的account信息
     * @param authentication
     * @return
     */
    private StoreAccount getAccount(Authentication authentication){
        StoreAccount account = new StoreAccount();
        BeanUtils.copyProperties((StoreAccount) authentication.getPrincipal(), account);
        account.setTicket("");//清除ticket
        return account;
    }
}
